﻿using System.IO.Compression;
using System.Reflection;

namespace AiMachineControl.Common
{
    /// <summary>
    /// 文件读写封装
    /// 注意：contentPath需要在Startup初始化
    /// </summary>
    public class FileHelper
    {
        static string _contentPath { get; set; }
        public FileHelper(string contentPath)
        {
            _contentPath = contentPath;
        }

        #region 文件上传辅助方法
        /// <summary>
        /// 获取文件类库的物理路径
        /// </summary>
        /// <param name="fileName">文件路径</param>
        public static string GetCurrPath(string fileName)
        {
            return Path.GetFullPath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + fileName);
        }

        /// <summary>
        /// 获取文件项目的物理路径
        /// </summary>
        /// <param name="fileName">文件路径</param>
        public static string GetRootPath(string fileName)
        {
            return Path.GetFullPath(_contentPath + fileName);
        }

        /// <summary>
        /// 获取文件站点的物理路径
        /// </summary>
        /// <param name="filePath">文件路径</param>
        public static string GetWebPath(string filePath)
        {
            return Path.GetFullPath(_contentPath + filePath);
        }

        /// <summary>
        /// 转换为字节数组
        /// </summary>
        /// <param name="fullName">文件物理路径含文件名</param>
        /// <returns>字节数组</returns>
        public static byte[] GetBinaryFile(string fullName)
        {
            if (File.Exists(fullName))
            {
                FileStream Fsm = null;
                try
                {
                    Fsm = File.OpenRead(fullName);
                    return ConvertStreamToByteBuffer(Fsm);
                }
                catch
                {
                    return new byte[0];
                }
                finally
                {
                    Fsm.Close();
                }
            }
            else
            {
                return new byte[0];
            }
        }

        /// <summary>
        /// 流转化为字节数组
        /// </summary>
        /// <param name="theStream">流</param>
        /// <returns>字节数组</returns>
        public static byte[] ConvertStreamToByteBuffer(Stream theStream)
        {
            int bi;
            MemoryStream tempStream = new System.IO.MemoryStream();
            try
            {
                while ((bi = theStream.ReadByte()) != -1)
                {
                    tempStream.WriteByte(((byte)bi));
                }
                return tempStream.ToArray();
            }
            catch
            {
                return new byte[0];
            }
            finally
            {
                tempStream.Close();
            }
        }

        /// <summary>
        /// 文件流上传文件
        /// </summary>
        /// <param name="binData">字节数组</param>
        /// <param name="fullName">文件物理路径含文件名</param>
        public static bool SaveFile(byte[] binData, string fullName)
        {
            FileStream fileStream = null;
            MemoryStream m = new MemoryStream(binData);
            try
            {
                fileStream = new FileStream(fullName, FileMode.Create);
                m.WriteTo(fileStream);
                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                m.Close();
                fileStream.Close();
            }
        }

        /// <summary>
        /// 删除本地单个文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="isXiangDui">是否相对路径</param>
        public static bool DeleteFile(string filePath,bool isXiangDui)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                return false;
            }
            string fullPath = GetWebPath(filePath);
            if (string.IsNullOrEmpty(fullPath))
            {
                return false;
            }
            if (isXiangDui)
            {
                if (File.Exists(fullPath))
                {
                    File.Delete(fullPath);
                    return true;
                }
            } else
            {
                if (Directory.Exists(filePath))
                {
                    Directory.Delete(filePath, true);
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 删除指定文件夹
        /// </summary>
        /// <param name="dirpath">文件绝对路径</param>
        public static bool DeleteDirectory(string dirPath)
        {
            if (string.IsNullOrEmpty(dirPath))
            {
                return false;
            }
            if (Directory.Exists(dirPath))
            {
                Directory.Delete(dirPath, true);
                return true;
            }
            return false;
        }

        /// <summary>
        /// 修改指定文件夹名称
        /// </summary>
        /// <param name="oldDirPath">旧绝对路径</param>
        /// <param name="newDirPath">新绝对路径</param>
        public static bool MoveDirectory(string oldDirPath, string newDirPath)
        {
            if (string.IsNullOrEmpty(oldDirPath))
            {
                return false;
            }
            if (Directory.Exists(oldDirPath))
            {
                Directory.Move(oldDirPath, newDirPath);
                return true;
            }
            return false;
        }

        /// <summary>
        /// 返回文件大小KB
        /// </summary>
        /// <param name="filePath">文件绝对路径</param>
        public static int GetFileSize(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                return 0;
            }
            if (File.Exists(filePath))
            {
                FileInfo fileInfo = new FileInfo(filePath);
                return ((int)fileInfo.Length) / 1024;
            }
            return 0;
        }

        /// <summary>
        /// 将大小转换成存储单位
        /// </summary>
        /// <param name="size">单位字节</param>
        /// <returns></returns>
        public static string ByteConvertStorage(long size)
        {
            string strSize = string.Empty;
            if (size < 1024.00)
                strSize = size + " B";
            else if (size >= 1024.00 && size < 1048576)
                strSize = Math.Round(Convert.ToDouble(size / 1024.00), 2) + " KB";
            else if (size >= 1048576 && size < 1073741824)
                strSize = Math.Round(Convert.ToDouble(size / 1024.00 / 1024.00), 2) + " MB";
            else if (size >= 1073741824)
                strSize = Math.Round(Convert.ToDouble(size / 1024.00 / 1024.00 / 1024.00), 2) + " GB";
            return strSize;
        }


        /// <summary>
        /// 返回文件扩展名，不含“.”
        /// </summary>
        /// <param name="filePath">文件全名称</param>
        /// <returns>string</returns>
        public static string GetFileExt(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                return string.Empty;
            }
            return Path.GetExtension(filePath).Trim('.');
        }

        /// <summary>
        /// 返回文件扩展名，含“.”
        /// </summary>
        /// <param name="filePath">文件全名称</param>
        /// <returns>string</returns>
        public static string GetFileFullExt(string filePath)
        {
            string ext = GetFileExt(filePath);
            if (!string.IsNullOrWhiteSpace(ext))
            {
                return $".{ext}";
            }
            else
            {
                return ext;
            }
        }

        /// <summary>
        /// 返回文件名，不含路径
        /// </summary>
        /// <param name="filePath">文件相对路径</param>
        /// <returns>string</returns>
        public static string GetFileName(string filePath)
        {
            return filePath.Substring(filePath.LastIndexOf(@"/") + 1);
        }

        /// <summary>
        /// 文件是否存在
        /// </summary>
        /// <param name="filePath">文件绝对路径</param>
        /// <returns>bool</returns>
        public static bool FileExists(string filePath)
        {
            if (File.Exists(filePath))
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 单文件压缩成ZIP
        /// </summary>
        /// <param name="fileSource">源文件路径</param>
        /// <param name="fileOut">ZIP文件路径</param>
        /// <param name="fileName">ZIP文件名：相对路径</param>
        /// <returns></returns>
        public static void SimpleFileZip(string fileSource, string fileOut, string fileName)
        {
            using (FileStream zipFileToOpen = new FileStream(fileOut, FileMode.OpenOrCreate))
            {
                using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Update))
                {
                    fileName = fileName.Trim(Path.DirectorySeparatorChar);
                    ZipFile(fileSource, fileName, archive);
                }
            }
        }

        /// <summary>
        /// 多文件压缩成ZIP
        /// </summary>
        /// <param name="fileSource">源文件路径</param>
        /// <param name="fileOut">ZIP文件路径</param>
        /// <param name="fileName">ZIP文件名</param>
        /// <returns></returns>
        public static void FilesZip(List<string> fileSources, string fileOut)
        {
            using (FileStream zipFileToOpen = new FileStream(fileOut, FileMode.OpenOrCreate))
            {
                using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Update))
                {
                    foreach (var file in fileSources)
                    {
                        string fileName = file.Replace(Path.DirectorySeparatorChar + "", "");
                        ZipFile(file, fileName, archive);
                    }
                }
            }
        }

        /// <summary>
        /// 压缩指定文件夹
        /// </summary>
        /// <param name="sourceDirectory"></param>
        /// <param name="fileOut"></param>
        public static void DirectoryZip(string sourceDirectory, string fileOut)
        {
            string[] allFiles = Directory.GetFiles(sourceDirectory, "", SearchOption.AllDirectories);
            using (FileStream zipFileToOpen = new FileStream(fileOut, FileMode.OpenOrCreate))
            {
                using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Update))
                {
                    foreach (var file in allFiles)
                    {
                        //获取压缩文件相对目录
                        string fileName = file.Replace(sourceDirectory + Path.DirectorySeparatorChar, "");
                        ZipFile(file, fileName, archive);
                    }
                }
            }
        }

        /// <summary>
        /// 解压文件到指定目录
        /// </summary>
        /// <param name="upZipDirPath"></param>
        /// <param name="zipPath"></param>
        public static bool UnZip(string upZipDirPath, string zipPath)
        {
            //解压文件路径为空时，默认为与压缩包同路径 解压
            if (string.IsNullOrEmpty(upZipDirPath))
            {
                upZipDirPath = zipPath.Replace(Path.GetFileName(zipPath), "");
            }
            //判断解压的文件路径 最后的字符是不是 \\
            //if (!upZipDirPath.EndsWith("\\"))
            //{
            //    upZipDirPath = "\\";
            //}
            if (!Directory.Exists(upZipDirPath))
                Directory.CreateDirectory(upZipDirPath);
            try
            {
                using (FileStream zipFileToOpen = new FileStream(zipPath, FileMode.Open))
                {
                    using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Read))
                    {
                        foreach (ZipArchiveEntry entry in archive.Entries)
                        {
                            if (entry.FullName.EndsWith("/") || entry.FullName.EndsWith("\\"))
                            {
                                continue;
                            }
                            // 定义解压文件的完整路径
                            string extractFilePath = Path.Combine(upZipDirPath, entry.FullName);
                            extractFilePath = extractFilePath.Replace("\\", "/");
                            //extractFilePath = extractFilePath.Replace("/", "\\");
                            if (File.Exists(extractFilePath))
                            {
                                File.Delete(extractFilePath);
                            }
                            entry.ExtractToFile(extractFilePath, overwrite: true);
                        }
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine("解压文件发生错误: " + ex.Message);
                return false;
            }
        }

        /// <summary>
        /// 解压文件到指定目录
        /// </summary>
        /// <param name="upZipDirPath"></param>
        /// <param name="zipPath"></param>
        public static bool UnZip2(string upZipDirPath, string zipPath)
        {
            System.IO.Compression.ZipFile.ExtractToDirectory(zipPath, upZipDirPath, overwriteFiles: true);
            return true;
        }

        /// <summary>
        /// 解压文件到指定目录
        /// </summary>
        /// <param name="upZipDirPath"></param>
        /// <param name="zipPath"></param>
        public static void UnZip3(string upZipDirPath, string zipPath)
        {
            if (!Directory.Exists(upZipDirPath))
                Directory.CreateDirectory(upZipDirPath);
            using (FileStream zipFileToOpen = new FileStream(zipPath, FileMode.Open))
            {
                using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Read))
                {
                    archive.ExtractToDirectory(upZipDirPath);
                }
            }
        }

        /// <summary>
        /// 生成压缩文件
        /// </summary>
        /// <param name="fileSource">源文件</param>
        /// <param name="fileName">压缩文件相对目录</param>
        /// <param name="archive">压缩文件包</param>
        private static void ZipFile(string fileSource, string fileName, ZipArchive archive)
        {
            ZipArchiveEntry readMeEntry = archive.CreateEntry(fileName);
            readMeEntry.LastWriteTime = File.GetLastWriteTime(fileSource);
            using (Stream stream = readMeEntry.Open())
            {
                byte[] bytes = File.ReadAllBytes(fileSource);
                stream.Write(bytes, 0, bytes.Length);
            }
        }

        #endregion
    }
}
